#include "Debug.h"

#ifdef __linux__
#include <sys/types.h>
#include <sys/syscall.h>
#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
#endif

// Some private global variables.
volatile const char *FileName;
volatile int LineNumber;

const char *Debug::GetFileName()
{
	return (const char *)FileName;
}
int Debug::GetLineNumber()
{
	return (int)LineNumber;
}

void Debug::SetFileAndLine(const char *file,int lineNumber)
{
	FileName = file;
	LineNumber = lineNumber;
}

// Display an error from a segmentation fault.
void Debug::ErrorHandler(int signum)
{
	#ifdef __linux__
	const char *errorType = "Segmentation fault";
	switch (signum) {
		case SIGFPE:
		{
			errorType = "Division by zero";
			break;
		}
		case SIGILL:
		{
			errorType = "Illegal instruction";
			break;
		}
		case SIGSEGV:
		{
			errorType = "Bad memory read/write";
			break;
		}
		case SIGBUS:
		{
			errorType = "Access misalligned memory or non-existent memory";
			break;
		}
	}
	printf("%s after %s line %d.\n",errorType,FileName,LineNumber);
	exit(signum);
	#endif
	return;	
}

// Add error handlers for segmenation faults not caught with try/catch.
void Debug::AddErrorHandler()
{
	#ifdef __linux__
	signal (SIGFPE, ErrorHandler); // division by 0
	signal (SIGILL, ErrorHandler); // illegal instruction
	signal (SIGSEGV, ErrorHandler); // bad memory read/write
	signal (SIGBUS, ErrorHandler); // access misalligned memory or non-existent memory	
	#endif
}

// Make sure the signals don't point to some function that might not exist in the future.
void Debug::RemoveErrorHandler()
{	
	#ifdef __linux__
	signal (SIGFPE, SIG_DFL); // division by 0
	signal (SIGILL, SIG_DFL); // illegal instruction
	signal (SIGSEGV, SIG_DFL); // bad memory read/write
	signal (SIGBUS, SIG_DFL); // access misalligned memory or non-existent memory	
	#endif
	return;
}

